﻿using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using DirectCanvas;
using WindowsFormsTest.Demos;
using WindowsFormsTest.Demos.CompositorDemo;
using WindowsFormsTest.Demos.EffectsDemo;
using WindowsFormsTest.Demos.GeometryDemo;
using WPFTestApp.Demos.EffectsDemo;
using PointF = DirectCanvas.Misc.PointF;
using Timer = System.Windows.Forms.Timer;
using Windows7.Multitouch.WinForms;
using WindowsFormsTest.Demos.GPGPU;
using DirectCanvas.Scenes;

namespace WindowsFormsTest
{
    public partial class Form1 : Form
    {
        const int WM_TABLET_QUERY_SYSTEM_GESTURE_STATUS = 716;
        const uint SYSTEM_GESTURE_STATUS_NOHOLD = 0x00000001;

        private DirectCanvasFactory m_directCanvasFactory;

        private Scene _m_currentScene;
        private Scene m_currentScene
        {
            get
            {
                return _m_currentScene;
            }
            set
            {
                if (_m_currentScene == value)
                    return;

                if (_m_currentScene != null)
                    _m_currentScene.DeactivateScene();

                _m_currentScene = value;

                if (_m_currentScene != null)
                    _m_currentScene.ActivateScene();
            }
        }
        private CompositorScene m_compositorScene;
        private GeometryScene m_geometryScene;
        private PixelShaderScene m_shaderScene;
        private WindowsFormsPresenter m_presenter;
        private SuperBlur m_superblurScene;
        private TransitionEffectScene m_transitionScene;
        private GPGPUScene m_gpgpuScene;

        private readonly Windows7.Multitouch.TouchHandler _touchHandler;

        bool ignoreMouse = false;

        public Form1()
        {
            InitializeComponent();

            var timer = new Timer();
            timer.Tick += new EventHandler(timer_Tick);
            timer.Interval = 10;
            timer.Start();


            panel1.MouseMove += panel1_MouseMove;
            panel1.MouseDown += panel1_MouseDown;
            panel1.MouseUp += panel1_MouseUp;


            /* Create a new DirectCanvasFactory.  This is the root class 
             * where almost all resources are created */
            m_directCanvasFactory = new DirectCanvasFactory();

            /* Create a new WindowsFromsPresenter, passing it our factory 
             * and our Winforms control that we want to render to */
            m_presenter = new WindowsFormsPresenter(m_directCanvasFactory, panel1);

            m_geometryScene = new GeometryScene(m_presenter);
            m_shaderScene = new PixelShaderScene(m_presenter);
            m_compositorScene = new CompositorScene(m_presenter);
            m_superblurScene = new SuperBlur(m_presenter);
            m_transitionScene = new TransitionEffectScene(m_presenter);
            m_gpgpuScene = new GPGPUScene(m_presenter);
            m_currentScene = m_gpgpuScene;

            _touchHandler = Factory.CreateHandler<Windows7.Multitouch.TouchHandler>(panel1);

            _touchHandler.TouchDown += OnTouchDownHandler;
            _touchHandler.TouchMove += OnTouchMoveHandler;
            _touchHandler.TouchUp += OnTouchUpHandler;
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            if (m_currentScene != null)
            {
                m_currentScene.Render();
            }

            m_presenter.Present();
        }

        void panel1_MouseUp(object sender, MouseEventArgs e)
        {
            if (ignoreMouse)
                return;
            if (m_currentScene == null ||
                e.Button != System.Windows.Forms.MouseButtons.Left)
                return;

            var point = new PointF((float)e.X, (float)e.Y);
            m_currentScene.SetInputState(0, InputStatus.Up, point);
        }

        void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            if (ignoreMouse)
                return;
            if (m_currentScene == null ||
                e.Button != System.Windows.Forms.MouseButtons.Left)
                return;

            var point = new PointF((float)e.X, (float)e.Y);
            m_currentScene.SetInputState(0, InputStatus.Down, point);
        }

        void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (ignoreMouse)
                return;
            if (m_currentScene == null)
                return;

            var point = new PointF((float)e.X, (float)e.Y);
            var status = InputStatus.Up;
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
                status = InputStatus.Down;
            m_currentScene.SetInputState(0, status, point);
        }

        //protected override void OnPaintBackground(PaintEventArgs e)
        //{
        //    /* no-op on purpose */
        //}

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            if (m_presenter != null)
                m_presenter.SetSize(panel1.ClientSize.Width, panel1.ClientSize.Height);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            m_currentScene = m_compositorScene;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            m_currentScene = m_shaderScene;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            m_currentScene = m_geometryScene;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            m_currentScene = m_superblurScene;
        }

        private void OnTouchDownHandler(object sender, Windows7.Multitouch.TouchEventArgs e)
        {
            PointF location = new PointF((float)e.Location.X, (float)e.Location.Y);
            m_currentScene.SetInputState(e.Id, InputStatus.Down, location);
            ignoreMouse = true;
        }

        private void OnTouchMoveHandler(object sender, Windows7.Multitouch.TouchEventArgs e)
        {
            PointF location = new PointF((float)e.Location.X, (float)e.Location.Y);
            m_currentScene.SetInputState(e.Id, InputStatus.Down, location);
            ignoreMouse = true;
        }

        private void OnTouchUpHandler(object sender, Windows7.Multitouch.TouchEventArgs e)
        {
            PointF location = new PointF((float)e.Location.X, (float)e.Location.Y);
            m_currentScene.SetInputState(e.Id, InputStatus.Up, location);
            ignoreMouse = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (Windows7.Multitouch.TouchHandler.DigitizerCapabilities.IsMultiTouchReady)
            {
                //FYI: Multi-touch available
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            m_currentScene = m_transitionScene;
            
        }

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_TABLET_QUERY_SYSTEM_GESTURE_STATUS:
                    {
                        uint result = 0;

                        result |= SYSTEM_GESTURE_STATUS_NOHOLD;

                        m.Result = (IntPtr)result;
                    }
                    break;

                default:
                    base.WndProc(ref m);
                    break;

            }

        }
    }
}
